package org.dtrd.modules.common.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.apache.shiro.SecurityUtils;
import org.dtrd.base.BaseController;
import org.dtrd.common.api.vo.Result;
import org.dtrd.common.system.vo.LoginUser;
import org.dtrd.common.util.DateUtils;
import org.dtrd.common.util.oConvertUtils;
import org.dtrd.config.system.Constant;
import org.dtrd.config.system.Constant.DoctorQueryPatientType;
import org.dtrd.config.system.SystemState.ResponseState;
import org.dtrd.modules.archive.entity.bean.ConfirmBean;
import org.dtrd.modules.archive.entity.po.DtrdEntRdArchivePhysical;
import org.dtrd.modules.archive.service.IDtrdEntRdArchiveBasicFamilyService;
import org.dtrd.modules.archive.service.IDtrdEntRdArchiveBasicService;
import org.dtrd.modules.archive.service.IDtrdEntRdPhysicalService;
import org.dtrd.modules.base.service.BaseCommonService;
import org.dtrd.modules.common.entity.bean.PatientListInfo;
import org.dtrd.modules.common.entity.po.DtrdViewRlGroupPatient;
import org.dtrd.modules.common.entity.request.*;
import org.dtrd.modules.content.tags.service.IDtrdEntRdTagService;
import org.dtrd.modules.doctor.entity.bean.DoctorInfo;
import org.dtrd.modules.doctor.entity.po.DtrdEntRdDoctor;
import org.dtrd.modules.doctor.entity.po.DtrdEntRdDoctorTeam;
import org.dtrd.modules.doctor.entity.po.DtrdRlDoctorTeamDoctor;
import org.dtrd.modules.doctor.job.DoctorStatisticInfoJob;
import org.dtrd.modules.doctor.service.IDtrdEntRdDoctorConcernPatientService;
import org.dtrd.modules.doctor.service.IDtrdEntRdDoctorService;
import org.dtrd.modules.doctor.service.IDtrdRlDoctorPatientService;
import org.dtrd.modules.doctor.service.IDtrdRlDoctorTeamDoctorService;
import org.dtrd.modules.flup.entity.bean.FlupRecord;
import org.dtrd.modules.flup.service.IDtrdEntRdFlupAppointmentRecordService;
import org.dtrd.modules.patient.entity.bean.PatientBasicAndFamilyInfo;
import org.dtrd.modules.content.tags.entity.bean.TagDetail;
import org.dtrd.modules.patient.entity.bean.PatientH5ListInfo;
import org.dtrd.modules.patient.entity.bean.PatientInfo;
import org.dtrd.modules.archive.entity.po.DtrdEntRdArchiveBasic;
import org.dtrd.modules.patient.entity.po.DtrdEntRdGroup;
import org.dtrd.modules.patient.entity.po.DtrdEntRdPatient;
import org.dtrd.modules.patient.entity.request.PatientRequest;
import org.dtrd.modules.patient.service.*;
import org.dtrd.modules.quartz.service.IQuartzJobService;
import org.dtrd.modules.system.entity.SysDepart;
import org.dtrd.modules.system.entity.SysUser;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

import static org.dtrd.common.constant.CommonConstant.*;
import static org.dtrd.config.system.SystemState.ResponseState.*;

/**
 * @Author: QR
 * @Date: 2021/9/30-12:34
 */
@Api(tags = "患者管理")
@RestController
@RequestMapping("/100/12/")
@Slf4j
public class PatientManagementController extends BaseController {

    @Autowired
    private IDtrdEntRdPatientService patientService;
    @Autowired
    private IDtrdEntRdArchiveBasicService basicService;
    @Autowired
    private IDtrdEntRdArchiveBasicFamilyService basicFamilyService;
    @Autowired
    private IDtrdRlGroupPatientService groupPatientService;
    @Autowired
    private IDtrdEntRdGroupService groupService;
    @Autowired
    private BaseCommonService baseCommonService;
    @Autowired
    private IDtrdEntRdFlupAppointmentRecordService appointmentRecordService;
    @Autowired
    private IDtrdRlPatientTagService patientTagRlService;
    @Autowired
    private IDtrdEntRdTagService tagService;
    @Autowired
    private IDtrdEntRdPhysicalService physicalService;
    @Autowired
    private IDtrdRlDoctorPatientService doctorPatientRlService;
    @Autowired
    private IDtrdEntRdDoctorConcernPatientService doctorConcernPatientService;
    @Autowired
    private IDtrdRlDoctorTeamDoctorService doctorTeamDoctorService;
    @Autowired
    private IDtrdEntRdDoctorService doctorService;
    @Autowired
    private IQuartzJobService quartzJobService;

    @GetMapping("1001212")
    public Result<?> getTeamDoctorListByDoctorId(@ApiParam(value = "医生ID", required = true) @Range(min = 1) @RequestParam Integer doctorId) {
        DtrdEntRdDoctor doctorInfo = doctorService.getById(doctorId);
        if (doctorInfo != null) {
            List<DtrdEntRdDoctorTeam> list = doctorTeamDoctorService.getTeamDoctorListByDoctorId(doctorId);
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("list", list);
            map.put("teamId", doctorInfo.getTeamId());
            return Result.OK(map);
        }
        return error(STATE_NO_RECORD);
    }

    @ApiOperation(value = "切换医生团队")
    @RequestMapping("1001213")
    public Result<?> selectTeam(@RequestBody @Validated SelectTeamRequest request) {
        DtrdEntRdDoctor doctorInfo = doctorService.getById(request.getDoctorId());
        if (doctorInfo == null) {
            return error(STATE_DATA_ERROR);
        }
        doctorInfo.setTeamId(request.getTeamId());
        boolean update = doctorService.updateById(doctorInfo);
        return update ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    @ApiOperation(value = "查询患者列表", response = PatientListInfo.class)
    @PostMapping("1001201")
    public Result<?> getPatientListV2(@RequestBody PatientPageRequest request) {
        // groupId == 0 表示查询未分组的患者
//        if (request.getGroupId() == null || request.getGroupId() < 0) {
//            return error(STATE_PARAMS_MISSING);
//        }
        Integer pageNum = getIntParam(request.getPageNum(), 1);
        Integer pageSize = getPageSize(request.getPageSize(), 100);
        IPage<PatientListInfo> patientInfo = new Page<>(pageNum, pageSize);
        Page<DtrdViewRlGroupPatient> page = new Page<>(pageNum, pageSize);
        // 设置查询条件：姓名 和 手机号 的模糊查询
        String name = null;
        String phone = null;
        if (StrUtil.isNotBlank(request.getKeyWord())) {
            String keyWord = request.getKeyWord();
            if (NumberUtil.isNumber(keyWord)) {
                phone = keyWord;
            } else {
                name = keyWord;
            }
        }
        // 处理标签筛选
        String tagIdsStr = request.getTagIds();
        List<Integer> patientIds = null;
        List<Integer> tagIds = null;
        try {
            if (StrUtil.isNotBlank(tagIdsStr)) {
                tagIds = Arrays.stream(tagIdsStr.split(","))
                        .map(Integer::parseInt)
                        .collect(Collectors.toList());
            }
        } catch (Exception e) {
            return Result.error("参数格式错误");
        }
        if (CollectionUtil.isNotEmpty(tagIds)) {
            List<Integer> ids = tagService.getPatientIdByTags(tagIds);
            if (CollectionUtil.isNotEmpty(ids)) {
                patientIds = ids;
            } else {
                return Result.OK(patientInfo);
            }
        }
        // 设置复诊状态状态的时间
        List<Date> dates = DateUtils.getWeekDate(new Date());
        Date startDate = dates.get(0);
        Date endDate = dates.get(6);
        Integer doctorId = request.getDoctorId();

        Integer teamId = Optional.ofNullable(doctorId).map(id -> doctorService.getById(id)).map(DtrdEntRdDoctor::getTeamId).orElse(null);
        List<Integer> teamDoctorIdList;
        log.info("teamId+++++++++++++++" + teamId);
        if (teamId != null) {
            teamDoctorIdList = doctorTeamDoctorService.getTeamDoctorIdListByTeamId(teamId);
        } else {
            teamDoctorIdList = doctorTeamDoctorService.getTeamDoctorIdList(doctorId);
        }

        if (doctorId != null && CollectionUtil.isEmpty(teamDoctorIdList)) {
            if (teamDoctorIdList == null) {
                teamDoctorIdList = new ArrayList<>();
            }
            teamDoctorIdList.add(doctorId);
        }

        log.info("teamDoctorIdList+++++++++++++++" + teamDoctorIdList);

        patientInfo = patientService.selectPatientInfo(page, teamDoctorIdList, request.getGroupId(), request.getStatus(), startDate, endDate, patientIds,
                request.getPatientName(), name, request.getPatientMobile(), phone);
        List<PatientListInfo> records = patientInfo.getRecords();
        records.forEach(record -> {
            if (record != null) {
                Integer patientId = record.getPatientId();
                // 设置预约记录
                if (record.getStatus() != null && record.getStatus() != Constant.FlupStatus.NoAppointment.getStatus()) {
                    FlupRecord flupRecord = appointmentRecordService.getPatientFlupRecordLatest(patientId);
                    Optional.ofNullable(flupRecord).ifPresent(record::setAppointmentRecord);
                }
                // 设置标签内容
                List<TagDetail> patientTags = patientTagRlService.getPatientTags(patientId);
                if (CollectionUtil.isNotEmpty(patientTags)) {
                    record.setTags(patientTags);
                }
                // 设置身高体重
                DtrdEntRdArchivePhysical physical = physicalService.getOne(Wrappers.lambdaQuery(DtrdEntRdArchivePhysical.class)
                        .eq(DtrdEntRdArchivePhysical::getPatientId, patientId));
                Optional.ofNullable(physical).ifPresent(record::parseFromPO);
            }
        });

        patientInfo.setRecords(records);
        // 记录系统日志
        String logContent = String.format("查询患者列表，查询条件：%s", request);
        baseCommonService.addLog(logContent, OPERATE_TYPE_QUERY);
        return Result.OK(patientInfo);
    }

    /**
     * @param request
     * @return
     * @deprecated 改为使用getPatientListV2 肖 2022-04-20 11:33:13
     */
    @Deprecated
    @ApiOperation(value = "查询患者列表", response = PatientListInfo.class)
    @PostMapping("10012010")
    public Result<?> getPatientList(@RequestBody PatientPageRequest request) {
        // groupId == 0 表示查询未分组的患者
        if (request.getGroupId() == null || request.getGroupId() < 0) {
            return error(STATE_PARAMS_MISSING);
        }
        Integer pageNum = getIntParam(request.getPageNum(), 1);
        Integer pageSize = getPageSize(request.getPageSize(), Constant.PAGESIZE);
        IPage<PatientListInfo> patientInfo = new Page<>(pageNum, pageSize);
        Page<DtrdViewRlGroupPatient> page = new Page<>(pageNum, pageSize);
        // 设置查询条件：姓名 和 手机号 的模糊查询
        String name = null;
        String phone = null;
        if (StrUtil.isNotBlank(request.getKeyWord())) {
            String keyWord = request.getKeyWord();
            if (NumberUtil.isNumber(keyWord)) {
                phone = keyWord;
            } else {
                name = keyWord;
            }
        }
        // 处理标签筛选
        String tagIdsStr = request.getTagIds();
        List<Integer> patientIds = null;
        List<Integer> tagIds = null;
        try {
            if (StrUtil.isNotBlank(tagIdsStr)) {
                tagIds = Arrays.stream(tagIdsStr.split(","))
                        .map(Integer::parseInt)
                        .collect(Collectors.toList());
            }
        } catch (Exception e) {
            return Result.error("参数格式错误");
        }
        if (CollectionUtil.isNotEmpty(tagIds)) {
            List<Integer> ids = tagService.getPatientIdByTags(tagIds);
            if (CollectionUtil.isNotEmpty(ids)) {
                patientIds = ids;
            } else {
                return Result.OK(patientInfo);
            }
        }
        // 设置复诊状态状态的时间
        List<Date> dates = DateUtils.getWeekDate(new Date());
        Date startDate = dates.get(0);
        Date endDate = dates.get(6);
        patientInfo = patientService.pagePatientInfo(page, phone, name, request.getGroupId(), request.getStatus(), startDate, endDate, patientIds,
                request.getPatientName(), request.getPatientMobile());
        List<PatientListInfo> records = patientInfo.getRecords();
        // 查询患者所属的 doctorId
        List<Integer> ids = records.stream()
                .map(PatientListInfo::getPatientId).collect(Collectors.toList());
        Map<Integer, Integer> pIdToDId = doctorPatientRlService.getPatientIdToDoctorIdMap(ids);

        log.info("PatientManagementController.getPatientList.[request] records = " + records);
        if (records != null) {
            records.forEach(record -> {
                if (record != null) {
                    Integer patientId = record.getPatientId();
                    // 设置预约记录
                    if (record.getStatus() != null && record.getStatus() != Constant.FlupStatus.NoAppointment.getStatus()) {
                        FlupRecord flupRecord = appointmentRecordService.getPatientFlupRecordLatest(patientId);
                        Optional.ofNullable(flupRecord).ifPresent(record::setAppointmentRecord);
                    }
                    // 设置标签内容
                    List<TagDetail> patientTags = patientTagRlService.getPatientTags(patientId);
                    if (CollectionUtil.isNotEmpty(patientTags)) {
                        record.setTags(patientTags);
                    }
                    // 设置身高体重
                    DtrdEntRdArchivePhysical physical = physicalService.getOne(Wrappers.lambdaQuery(DtrdEntRdArchivePhysical.class)
                            .eq(DtrdEntRdArchivePhysical::getPatientId, patientId));
                    Optional.ofNullable(physical).ifPresent(record::parseFromPO);
                }
            });
        }
        if (MapUtil.isNotEmpty(pIdToDId)) {
            records.forEach(r -> r.setDoctorId(pIdToDId.get(r.getPatientId())));
        }

        patientInfo.setRecords(records);
        // 记录系统日志
        String logContent = String.format("查询患者列表，查询条件：%s", request);
        baseCommonService.addLog(logContent, OPERATE_TYPE_QUERY);
        return Result.OK(patientInfo);
    }

    @ApiOperation(value = "查询患者基本信息", response = PatientBasicAndFamilyInfo.class)
    @PostMapping("1001202")
    public Result<?> getPatientBasicInfo(@RequestBody PatientRequest request) {
        if (request == null) {
            return error(STATE_PARAMS_MISSING);
        }
        Integer patientId = request.getPatientId();
        String patientMobile = request.getMobile();
        String patientName = request.getPatientName();
        // patientId , mobile 和 patientName 有一个即可
        if (isIntParamInvalid(patientId) && StrUtil.isBlank(patientMobile) && StrUtil.isBlank(patientName)) {
            return error(STATE_PARAMS_MISSING);
        }
        List<PatientBasicAndFamilyInfo> infos = basicService.getPatientBasicInfoByRequest(request);
        String logContent = String.format("查询患者基本信息，查询患者id：%d", patientId);
        baseCommonService.addLog(logContent, OPERATE_TYPE_QUERY);
        return CollectionUtil.isNotEmpty(infos) ? Result.OK(infos) : error(STATE_NO_RECORD);
    }

    @ApiOperation("添加/修改患者基本信息")
    @PostMapping("1001203")
    public Result<?> saveOrUpdatePatientBasicInfo(@RequestBody @Validated PatientBasicAndFamilyInfo info) {
        PatientInfo patientInfo = patientService.selectByMobile(info.getPatientMobile());
        if (info.getPatientId() == null && patientInfo != null) {
            return Result.error(STATE_OPERATION_FAILURE.getCode(), "手机号已被绑定");
        } else {
            boolean result = basicService.saveOrUpdatePatientInfo(info);
            String logContent = String.format("添加/修改患者基本信息，编辑患者id：%d", info.getPatientId());
            baseCommonService.addLog(logContent, OPERATE_TYPE_SAVE_OR_UPDATE);
            return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
        }
    }

    @ApiOperation("批量删除患者")
    @PostMapping("1001204")
    public Result<?> batchRemovePatient(@RequestBody BatchOperationRequest request) {
        if (request == null || CollectionUtil.isEmpty(request.getPatientIds())) {
            return error(STATE_PARAMS_MISSING);
        }
        patientService.removeByIds(request.getPatientIds());
        basicService.removeByPatientIds(request.getPatientIds());
        basicFamilyService.removeByPatientIds(request.getPatientIds());
        // 补充复诊记录与医患关联删除操作 肖 2022-07-02 17:49:56
        doctorPatientRlService.deleteRecordByPatientIds(request.getPatientIds());
        appointmentRecordService.removeRecordByPatientIds(request.getPatientIds());
        // 补充分组记录删除  肖 2022-07-04 15:17:39
        groupPatientService.deleteRecordByPatientIds(request.getPatientIds());
        // 触发医生统计任务 肖 2022-07-07 16:43:03
        quartzJobService.triggerJobByClassName(DoctorStatisticInfoJob.class.getName());
        String logContent = String.format("批量删除患者，删除患者id集合：%s", request.getPatientIds().toString());
        baseCommonService.addLog(logContent, OPERATE_TYPE_DELETE);
        return Result.OK();
    }

    @ApiOperation(value = "查询分组列表", response = DtrdEntRdGroup.class)
    @PostMapping("1001205")
    public Result<?> getGroupList(@RequestBody GroupRequest request) {
        if (request == null || StrUtil.isBlank(request.getOrgCode())) {
            return error(STATE_PARAMS_MISSING);
        }
        List<DtrdEntRdGroup> list = groupService.list(new LambdaQueryWrapper<>(DtrdEntRdGroup.class)
                .eq(DtrdEntRdGroup::getOrgCode, request.getOrgCode())
                .eq(DtrdEntRdGroup::getIsDel, 0));
        String logContent = String.format("查询分组列表，查询条件：%s", request);
        baseCommonService.addLog(logContent, OPERATE_TYPE_QUERY);
        return Result.OK(list);
    }

    @ApiOperation("批量患者分组")
    @PostMapping("1001206")
    public Result<?> batchGroupPatients(@RequestBody BatchOperationRequest request) {
        Integer groupId = request.getGroupId();
        if (groupId == null
                || CollectionUtil.isEmpty(request.getPatientIds())) {
            return error(STATE_PARAMS_MISSING);
        }
        if (groupId > 0) {
            // 判断 groupId 是否有效
            DtrdEntRdGroup queryGroup = groupService.getById(groupId);
            if (queryGroup == null) {
                return error(STATE_PARAMS_ERROR);
            }
        }
        boolean result = groupPatientService.batchGroupPatients(groupId, request.getPatientIds());
        String logContent = String.format("批量患者分组，患者id集合：%s, 分组id: %s", request.getPatientIds().toString(), groupId);
        baseCommonService.addLog(logContent, OPERATE_TYPE_ADD);
        return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    @ApiOperation(value = "确认患者信息是否完成")
    @PostMapping("1001207")
    public Result<?> confirmPatient(@RequestBody ConfirmBean request) {
        Integer patientId = request.getPatientId();
        if (isIntParamInvalid(patientId)) {
            return error(STATE_PARAMS_MISSING);
        }
        Integer isFinished = request.getIsFinished();
        if (isFinished != Constant.FINISHED && isFinished != Constant.UN_FINISHED) {
            return error(STATE_PARAMS_ERROR);
        }
        DtrdEntRdArchiveBasic archive = basicService.getOne(Wrappers.lambdaQuery(DtrdEntRdArchiveBasic.class)
                .eq(DtrdEntRdArchiveBasic::getPatientId, patientId));
        if (archive == null) {
            return error(STATE_PARAMS_ERROR);
        }
        archive.setIsFinished(isFinished);
        boolean result = basicService.updateById(archive);
        String logContent = String.format("确认患者id：%d 基本信息档案完成", patientId);
        baseCommonService.addLog(logContent, OPERATE_TYPE_UPDATE);
        return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    @ApiOperation("生成患者二维码")
    @GetMapping("1001208")
    public Result<?> generateQrCode(@ApiParam(value = "患者ID", required = true) @RequestParam Integer patientId) {
        String qrCode = patientService.generateQrCode(patientId);
        return qrCode == null ? error(STATE_OPERATION_FAILURE) : Result.OK(qrCode);
    }

    @ApiOperation("查询医患聊天室ID")
    @GetMapping("1001209")
    public Result<?> getChatroomId(@ApiParam(value = "患者ID", required = true) @RequestParam Integer patientId, @ApiParam(value = "医生ID", required = false) @RequestParam Integer doctorId) {
        log.info("PatientManagementController.getChatroomId.[patientId = {}, doctorId={}", patientId, doctorId);
        String chatroomId = doctorPatientRlService.getChatroomIdByPatientId(patientId, doctorId);
        return chatroomId == null ? error(STATE_NO_RECORD) : Result.OK(chatroomId);
    }

    @ApiOperation("设置为重点关注")
    @PostMapping("/1001210")
    public Result<?> addConcernPatient(@RequestBody @Validated ConcernPatientRequest request) {
        log.info("PatientManagementController.addConcernPatient.[request =" + request);
        boolean result = doctorConcernPatientService.concernPatient(request.getDoctorId(), request.getPatientId(), request.getPatientsCollected(), request.getOrgCode());
        return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    @ApiOperation("查询关联患者列表")
    @PostMapping("/1001211")
    @ApiResponses(@ApiResponse(code = 0, message = "", response = PatientH5ListInfo.class))
    public Result<?> getRelationPatientList(@RequestBody @Validated RelationPatientPageRequest request) {
        handlePageRequest(request);
        Integer pageNum = request.getPageNum();
        Integer pageSize = request.getPageSize();
        IPage<PatientH5ListInfo> patientPageInfo;
        Integer doctorId = request.getDoctorId();
        Integer teamId = Optional.ofNullable(doctorId).map(id -> doctorService.getById(id)).map(DtrdEntRdDoctor::getTeamId).orElse(null);
        List<Integer> teamDoctorIdList;
        log.info("teamId+++++++++++++++"+teamId);
        if (teamId != null) {
            teamDoctorIdList = doctorTeamDoctorService.getTeamDoctorIdListByTeamId(teamId);
        } else {
            teamDoctorIdList = doctorTeamDoctorService.getTeamDoctorIdList(doctorId);
        }

        if (doctorId != null && CollectionUtil.isEmpty(teamDoctorIdList)) {
            if (teamDoctorIdList == null) {
                teamDoctorIdList = new ArrayList<>();
            }
            teamDoctorIdList.add(doctorId);
        }
        // List<Integer> teamDoctorIdList = doctorTeamDoctorService.getTeamDoctorIdList(doctorId);
        // if (doctorId != null && CollectionUtil.isEmpty(teamDoctorIdList)) {
        //     if (teamDoctorIdList == null) {
        //         teamDoctorIdList = new ArrayList<>();
        //     }
        //     teamDoctorIdList.add(doctorId);
        // }
        // 前后端约定 2 为 重点关注 肖 2022年06月20日14:20:04
        if (request.getType() == DoctorQueryPatientType.CONCERN.getType()) {
            // 重点关注患者列表
            patientPageInfo = doctorPatientRlService.pageConcernPatientList(doctorId, pageNum, pageSize);
        } else {
            patientPageInfo = doctorPatientRlService.pageRelationPatientList(teamDoctorIdList, doctorId, request.getType(), request.getSubType(), pageNum, pageSize);
        }
        return Result.OK(patientPageInfo);
    }

}

